/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.luminia.lightweightstopwatch;

import android.app.Activity;
import android.content.Context;
//import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;	

import com.luminia.lightweightstopwatch.R;



/**
* This Class represents the Main StopWatch Activity.
* 
* @see android.view.View.OnClickListener
* 
*/
public class StopWatchActivity extends Activity implements OnClickListener{

	private static final String TAG = "StopWatchActivity";
	static final private int INFO = Menu.FIRST+2;
	static final private int GRAPH = Menu.FIRST+1;
	static final private int VOLUME = Menu.FIRST;
	private ArrayList<String> laps;
	private ArrayAdapter<String> lapsAdapter;
	private TextView hours;
	private TextView minutes;
	private TextView seconds;
	private TextView milliseconds;
	private Button btnTime;
	private Button btnStop;
	private Button btnClear;
	private ListView listLaps;
	private Thread th;
	//private Runnable updateTimeView;
	int min, sec, mil;
	
	//Settings Variable
	private static final String PREFS_NAME = "UserPreferences";
	private volatile SharedPreferences settings;
    
	
	private volatile boolean backgroundPause = false;
 
	private StopWatch stopWatch;
 
	/*
	 *  Class overridden methods 
	 */
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initComponents();
    }
    
    @Override
    protected void onResume() {
    	Log.i(TAG,"onResume");
    	backgroundPause = false;
    	if (!stopWatch.isStopped()) {
    		th = new Thread(null, updateTimeView, "updateTimeView");
    		th.start();
    	}
    	super.onResume();
    }
    
    @Override 
    protected void onPause() {
    	Log.i(TAG,"onPause");
    	backgroundPause = true;
    	super.onPause();
 
    }
    @Override
	public void onClick(View v) {
 
		if(v == btnTime) { 
			timePressed();
 		}
		else if(v == btnStop) {
			lapsPressed();
		}
		else if(v == btnClear) {
		}
 
    }
    
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		//Group 1
		int group1 = 1;
		menu.add(group1, INFO, Menu.NONE, R.string.info).setIcon(R.drawable.ic_menu_info_details);
		menu.add(group1, GRAPH, Menu.NONE, R.string.graph).setIcon(R.drawable.graph);
		
		//Group 2
		int group2 = 2;
		if ( settings.getBoolean("volume_control", true) == true ){
			menu.add(group2, VOLUME, Menu.NONE, R.string.volume_control_on).setIcon(R.drawable.volume_control_on);
		}
		else {
			menu.add(group2, VOLUME, Menu.NONE, R.string.volume_control_off).setIcon(R.drawable.volume_control_off);
		}
		return true;
	}
 
	
	
	
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);
		switch(item.getItemId()){
		
			case INFO:
				Toast.makeText(this, "Developed by Luminia.", Toast.LENGTH_LONG).show();
				break;
 			
			case VOLUME:
		        Editor editor = settings.edit();
				if ( settings.getBoolean("volume_control", true) == true ) {
					item.setIcon(R.drawable.volume_control_off);
					item.setTitle(R.string.volume_control_off);
					editor.putBoolean("volume_control", false);
					Toast.makeText(this, R.string.volume_alert_off, Toast.LENGTH_LONG).show();
				}
				else{
					item.setIcon(R.drawable.volume_control_on);
					item.setTitle(R.string.volume_control_on);
					editor.putBoolean("volume_control", true);
					Toast.makeText(this, R.string.volume_alert_on, Toast.LENGTH_LONG).show();
				}
				
				editor.commit();
				break;
				
			/**
			 * TODO Add Graph Support
			 */
			//case GRAPH:
				//Intent mIntent = new Intent(this, MyActivity.class);
				//startActivity(mIntent);
				//return true;
			}
		
		// In case I didn't handle the menu item
		return false;
	} 
	
	
	
	
	/*
	 *  Class own methods
	 */	
	
	
	private void initComponents() {
		 
		stopWatch = new StopWatch(this);
		laps = stopWatch.getLaps();
		settings = this.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);

		hours = (TextView) findViewById(R.id.hours);
		minutes = (TextView) findViewById(R.id.minutes);
		seconds = (TextView) findViewById(R.id.seconds);
		milliseconds = (TextView) findViewById(R.id.milliseconds);
		
		btnTime = (Button) findViewById(R.id.btnTime);
    	btnTime.setOnClickListener(this);
    	btnStop = (Button) findViewById(R.id.btnStop);
    	btnStop.setOnClickListener(this);
 
    	listLaps = (ListView) findViewById(R.id.listLaps);
 
    	lapsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, laps);
    	listLaps.setAdapter(lapsAdapter);
    	
    	if (!stopWatch.isStopped()) {
    		th = new Thread(null, updateTimeView, "updateTimeView");
    		th.start();
    	}
    	else{
			updateComponents(stopWatch.getTime());
    	}
    	changeButtonUi();
    }
	
	private void resetComponents() {
		hours.setText("00");
		minutes.setText("00");
		seconds.setText("00");
		milliseconds.setText("00");
	}
	
	private String getTimeString() {
		
		return hours.getText() + ":"
				+ minutes.getText() + ":"
				+ seconds.getText() + "."
				+ milliseconds.getText();		
	}
	
	
	/**
     * Convert a millisecond duration to a string format
     * and update the stopwatch UI.
     * 
     * @param millis  A duration in milliseconds to convert to a string form
     * to be show at stopwatch UI.
     */
	private void updateComponents(long millis) {
    
        if(millis < 0) {
            throw new IllegalArgumentException("Duration must be greater than zero!");
        }
                
        /* There is a problem with Android documentation
         * http://developer.android.com/reference/java/util/concurrent/TimeUnit.html
         * Great part this functionality is only available at java6
         * and although the documentation of Android says it have
         * this, it have not, only implemented the Java5 version of
         * TimeUnit. This make my code bellow unsuitable for Android.         *                 
        
        long days = TimeUnit.MILLISECONDS.toDays(millis);
        millis -= TimeUnit.DAYS.toMillis(days);
        long hours = TimeUnit.MILLISECONDS.toHours(millis);
        millis -= TimeUnit.HOURS.toMillis(hours);
        long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
        millis -= TimeUnit.MINUTES.toMillis(minutes);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
		*
		*/
        
        String ms = ( Integer.toString( (int) (millis) % 1000 ) ) + "00";
        String s =  ( Integer.toString( (int) (millis / 1000) % 60 ) )  ;
        String m =  ( Integer.toString( (int) ((millis / (1000*60)) % 60) ) ) ;
        String h =  ( Integer.toString( (int) ((millis / (1000*60*60)) % 100) ) ) ;
        
       
        

        hours.setText( timeLabel(h) );
        minutes.setText( timeLabel(m) );
		seconds.setText( timeLabel(s) );
		milliseconds.setText( ms.substring(0, 3) );
        
    }
	
	 private String timeLabel(String stringTime) {
     	if (stringTime.length() == 1)
     		return "0"+stringTime;     		
     	return stringTime;
     }

	
	private void changeButtonUi(){
		if(!stopWatch.isStopped()) { 
			btnTime.setText(R.string.stop);
			btnTime.setBackgroundResource(R.drawable.stop_button);
			btnStop.setText(R.string.lap);
		}
		else{
			btnTime.setText(R.string.start);
			btnTime.setBackgroundResource(R.drawable.start_button);
			btnStop.setText(R.string.clear);			
		}
	}
	
	private void timePressed(){
		if(stopWatch.isStopped()) { 
			stopWatch.start();
			th = new Thread(null, updateTimeView, "updateTimeView");
    		th.start();
		}
		else{ 
			stopWatch.stop();						
		}
		changeButtonUi();
				
	}
	
	private void lapsPressed(){
		if(stopWatch.isStopped()){
			stopWatch.clear();
			resetComponents();
			lapsAdapter.notifyDataSetChanged();
		}
		else{
			//Insert the last element into the first position
			String string_time = getTimeString();
			int laps_size = stopWatch.getLapsSize() + 1;
			//String string_time = getTimeString();
			if (laps_size > 1) {
				//int laps_size = stopWatch.getLapsSize() + 1;
				//String string_time = getTimeString();
				if (laps_size > 1) {
					
				}
			}
			laps_size = stopWatch.addLap(string_time);
			Log.i(TAG,"Size of laps"+laps_size);
			lapsAdapter.notifyDataSetChanged();
		}
	}
	
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
    	
    	if ( settings.getBoolean("volume_control", true) == true ) {

    		int action = event.getAction();
    		int keyCode = event.getKeyCode();
    		switch (keyCode) {
            	case KeyEvent.KEYCODE_VOLUME_UP:
            		if (action == KeyEvent.ACTION_UP) {
            			timePressed();
            		}
            		return true;
            	case KeyEvent.KEYCODE_VOLUME_DOWN:
            		if (action == KeyEvent.ACTION_DOWN) {
            			lapsPressed();
            		}
            		return true;
            	default:
            		return super.dispatchKeyEvent(event);
    		}
    	} 
    	else
    		return super.dispatchKeyEvent(event);
    }
 
    private Runnable updateTimeView = new Runnable() {
		@SuppressWarnings("static-access")
		@Override
		public void run() {
			Log.i(TAG,"Start updateTimeView thread");
			while(!stopWatch.isStopped() && !backgroundPause) {
				runOnUiThread(calculateCurrentTime);
				try {
					th.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			Log.i(TAG,"Stop updateTimeView thread");
		}
	};
    
	private Runnable calculateCurrentTime = new Runnable() { 
		@Override
		public void run() { 
			updateComponents(stopWatch.getTime());
		}
	};
	
}
	
	
